package cn.bluemobi.app.utils;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * @Description 图片操作工具类
 * 
 * @依赖：servlet-api.jar,spring-core-3.1.2.RELEASE.jar,spring-web-3.1.2.RELEASE.jar
 * @date 2014-09-25 11:49:48
 * @author 龙哲
 */
public class ImageUtils {

	private static String imagePath = PathUtils.getProjectName()
			+ "upload/temp/";
	private static String imageSuoluePath = PathUtils.getProjectName()
			+ "upload/suolue/";

	/**
	 * @Description 缩放图片
	 * @param 参数列表
	 *            source 源图片,targetW 缩放后的宽度,targetH 缩放后的长度;
	 * @return BufferedImage 缩放后的图片
	 * @date 2014-7-30 下午03:08:52
	 * @author 龙哲
	 */
	private static BufferedImage getResizedImage(BufferedImage source,
			int targetW, int targetH) {
		int type = source.getType();
		BufferedImage target = null;
		// targetW，targetH分别表示目标长和宽
		double sx = (double) targetW / source.getWidth();
		double sy = (double) targetH / source.getHeight();
		// 如果目标长度超出现有长度，则返回原图，如果目标长度超出现有长度，则返回原图
		if (targetW >= source.getWidth() || targetH >= source.getHeight()) {
			return source;
		}
		// 这里想实现在targetW，targetH范围内实现等比缩放。如果不需要等比缩放
		// 则将下面的if else语句注释即可
		if (sx > sy) {
			sx = sy;
			targetW = (int) (sx * source.getWidth());
		} else {
			sy = sx;
			targetH = (int) (sy * source.getHeight());
		}
		if (type == BufferedImage.TYPE_CUSTOM) { // handmade
			ColorModel cm = source.getColorModel();
			WritableRaster raster = cm.createCompatibleWritableRaster(targetW,
					targetH);
			boolean alphaPremultiplied = cm.isAlphaPremultiplied();
			target = new BufferedImage(cm, raster, alphaPremultiplied, null);
		} else {
			target = new BufferedImage(targetW, targetH, type);
		}
		Graphics2D g = target.createGraphics();
		// smoother than exlax:
		g.setColor(Color.WHITE);
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
		g.dispose();
		return target;
	}

	/**
	 * @Description 等比缩放图片
	 * @param 参数列表
	 *            file 源图片,targetW 缩放后的宽度,targetH 缩放后的长度;
	 * @return BufferedImage 缩放后的图片
	 * @date 2014-7-30 下午03:08:52
	 * @author 龙哲
	 */
	public static BufferedImage resize(File file, int width, int height) {
		try {
			BufferedImage srcImage = ImageIO.read(file);
			if (width > 0 || height > 0) {
				srcImage = getResizedImage(srcImage, width, height);
			}
			return srcImage;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 图片上传 并保存缩略图(上传的文件保存在项目同级的目录下) imgWidth 原图宽度， imgHeight 原图高度 ，imgURL 原图路径，
	 * imgThu 缩略图路径
	 * 
	 * @param request
	 * @param imageFile
	 * @param needSmallImage
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> saveImage(ServletRequest request,
			MultipartFile imageFile, boolean needSmallImage) throws Exception {
		Random rand = new Random();
		Map<String, Object> pathMap = new HashMap<String, Object>();
		if (null != imageFile
				&& imageFile.getOriginalFilename().toLowerCase().trim()
						.length() != 0) {
			String originalFileName = imageFile.getOriginalFilename()
					.toLowerCase();
			String filetype = originalFileName.substring(originalFileName
					.indexOf("."));
			String timeMillis = String.valueOf(System.currentTimeMillis());
			String path = imagePath + timeMillis + "_" + rand.nextInt(1000000)
					+ filetype;
			String webpath = getWebPath(request);
			// 获取项目在磁盘上面的物理路径
			File image = new File(webpath + path);
			File dir = image.getParentFile();
			if (!dir.exists()) {
				dir.mkdirs();
			}
			FileCopyUtils.copy(imageFile.getBytes(), image);

			// 获取图片属性
			BufferedImage imgBufferedImage = ImageIO.read(image);
			// 原图宽度
			pathMap.put("imgWidth", imgBufferedImage.getWidth());
			// 原图高度
			pathMap.put("imgHeight", imgBufferedImage.getHeight());
			// 原图URL
			pathMap.put("imgURL", request.getScheme()+"://"+ request.getServerName()+":"+request.getLocalPort()+"/" + path);
			if (needSmallImage) {
				String suoluepath = imageSuoluePath + timeMillis + "_"
						+ rand.nextInt(1000000) + filetype;
				try {
					FileCopyUtils.copy(imageFile.getBytes(), image);
					BufferedImage bi = ImageUtils.resize(image, 500, 500);// 根据上传的图片文件生成对应的缩略图
					File smallfile = new File(new File(webpath) + "/"
							+ suoluepath);
					if (!smallfile.getParentFile().exists()) {// 如果文件夹不存在
						smallfile.getParentFile().mkdirs();// 创建上传文件夹
					}
					ImageIO.write(bi, "jpg", smallfile);// 将缩略图写入服务器端的制定文件夹中
				} catch (IOException e) {
					e.printStackTrace();
				}
				// 缩略图路径
				pathMap.put("imgThu", "/" + suoluepath);
			} else {
				// 缩略图路径
				pathMap.put("imgThu", "");
			}
		}
		System.out.println();
		return pathMap;
	}
	
	/**
	 * 改变图片尺寸
	 * 
	 * @param srcFileName
	 *            源图片路径
	 * @param width
	 *            修改后的宽度
	 * @param height
	 *            修改后的高度
	 */
    public static void zoomImage(File f, int toWidth, int toHeight) {  
          
        BufferedImage result = null;  
  
        try {  
            BufferedImage im = ImageIO.read(f);  
  
            /* 新生成结果图片 */  
            result = new BufferedImage(toWidth, toHeight,BufferedImage.TYPE_INT_RGB);  
            result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight,java.awt.Image.SCALE_SMOOTH), 0, 0, null); 
            ImageIO.write(result, "jpg", new File(f.getPath()));// 画图
        } catch (Exception e) {  
            System.out.println("创建缩略图发生异常" + e.getMessage());  
        }  
          
    }  

	/**
	 * 缩放图像（按高度和宽度缩放）
	 * 
	 * @Description
	 * @param f
	 *            源图像文件
	 * @param height
	 *            缩放后的高度
	 * @param width
	 *            缩放后的宽度
	 * @param bb
	 *            比例不对时是否需要补白：true为补白; false为不补白
	 * @date 2017-2-21
	 * @author reny01
	 */
	@SuppressWarnings("static-access")
	public static void scale(File f, int height, int width, boolean bb) {
		try {
			double ratio = 0.0; // 缩放比例
			BufferedImage bi = ImageIO.read(f);
			Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
			// 计算比例
			if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
				if (bi.getHeight() > bi.getWidth()) {
					ratio = (new Integer(height)).doubleValue()
							/ bi.getHeight();
				} else {
					ratio = (new Integer(width)).doubleValue() / bi.getWidth();
				}
				AffineTransformOp op = new AffineTransformOp(AffineTransform
						.getScaleInstance(ratio, ratio), null);
				itemp = op.filter(bi, null);
			}
			if (bb) {// 补白
				BufferedImage image = new BufferedImage(width, height,
						BufferedImage.TYPE_INT_RGB);
				Graphics2D g = image.createGraphics();
				g.setColor(Color.white);
				g.fillRect(0, 0, width, height);
				if (width == itemp.getWidth(null))
					g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
							itemp.getWidth(null), itemp.getHeight(null),
							Color.white, null);
				else
					g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
							itemp.getWidth(null), itemp.getHeight(null),
							Color.white, null);
				g.dispose();
				itemp = image;
			}
			ImageIO.write((BufferedImage) itemp, "JPEG", new File(f.getPath()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @Description 图像切割并上传(按指定起点坐标和宽高切割)
	 * @param srcImageFile
	 *            源图像地址
	 * @param result
	 *            切片后的图像地址
	 * @param x
	 *            目标切片起点坐标X
	 * @param y
	 *            目标切片起点坐标Y
	 * @param w
	 *            目标切片宽度
	 * @param h
	 *            目标切片高度
	 * @date 2017-2-21
	 * @author reny01
	 */
	public static Map<String, Object> saveCut(ServletRequest request,
			MultipartFile imageFile, int x, int y, int w, int h) {
		Random rand = new Random();
		Map<String, Object> pathMap = new HashMap<String, Object>();
		try {
			if (null != imageFile
					&& imageFile.getOriginalFilename().toLowerCase().trim()
							.length() != 0) {
				String originalFileName = imageFile.getOriginalFilename()
						.toLowerCase();
				String filetype = originalFileName.substring(originalFileName
						.indexOf("."));
				String timeMillis = String.valueOf(System.currentTimeMillis());
				String path = imagePath + timeMillis + "_"
						+ rand.nextInt(1000000) + filetype;
				String webpath = getWebPath(request);
				// 获取项目在磁盘上面的物理路径
				File image = new File(webpath + path);
				File dir = image.getParentFile();
				if (!dir.exists()) {
					dir.mkdirs();
				}
				FileCopyUtils.copy(imageFile.getBytes(), image);
				// 获取图片属性
				BufferedImage imgBufferedImage = ImageIO.read(image);
				
				int srcWidth = imgBufferedImage.getWidth(); // 源图宽度
				int srcHeight = imgBufferedImage.getHeight(); // 源图高度
				
				//图片比例
				Double bili = Double.parseDouble(srcWidth + "") / Double.parseDouble(510+"");

				if (srcWidth > 0 && srcHeight > 0) {
					Image image2 = imgBufferedImage.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
					int x1 = (int) (bili*x);
					int y1 = (int) (bili*y);
					int w1 = (int) (bili*w);
					int h1 = (int) (bili*h);
					
					System.out.println(x1);
					System.out.println(y1);
					System.out.println(w1);
					System.out.println(h1);
					// 四个参数分别为图像起点坐标和宽高
					ImageFilter cropFilter = new CropImageFilter(x1,y1,w1,h1);
					Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image2.getSource(),cropFilter));
					
					BufferedImage tag = new BufferedImage(w1, h1,BufferedImage.TYPE_INT_RGB);
					Graphics g = tag.getGraphics();
					g.drawImage(img, 0, 0,null); // 绘制切割后的图
					g.dispose();
					// 输出为文件
					ImageIO.write(tag, "JPEG", new File(image.getPath()));
				}
				// 获取最新属性
				imgBufferedImage = ImageIO.read(image);
				// 原图宽度
				pathMap.put("imgWidth", imgBufferedImage.getWidth());
				// 原图高度
				pathMap.put("imgHeight", imgBufferedImage.getHeight());
				// 原图URL
				pathMap.put("imgURL", "/" + path);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return pathMap;
	}

	/**
	 * @Description 传入原图名称,获得一个以时间格式的新名称
	 * @param 参数列表
	 *            fileName 原图名称;
	 * @return String 时间格式名称
	 * @date 2014-7-30 下午03:08:52
	 * @author 龙哲
	 */
	public static String generateFileName(String fileName) {
		DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		String formatDate = format.format(new Date());
		int random = new Random().nextInt(10000);
		int position = fileName.lastIndexOf(".");
		String extension = fileName.substring(position);
		return formatDate + random + extension;
	}

	/**
	 * @Description 获取项目在tomcat下的地址
	 * @param 参数列表
	 *            request request 请求;
	 * @return String 时间格式名称
	 * @date 2014-7-30 下午03:08:52
	 * @author 龙哲
	 */
	public static String getWebPath(ServletRequest request) {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpSession session = req.getSession(true);
		String path = session.getServletContext().getRealPath("/").replace(
				File.separator, "/");
		String[] paths = path.split("/");
		StringBuffer buff = new StringBuffer();
		for (int i = 0; i < paths.length - 1; i++) {
			buff.append(paths[i] + "/");
		}
		String newpath = buff.toString();
		return newpath;
	}
}
